package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.FocusUser;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.service.CommentApi;
import com.tanhua.service.FocusUserApi;
import com.tanhua.service.UserInfoApi;
import com.tanhua.service.VideoApi;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author げっしょく
 * @date 2021/11/1
 */
@Service
public class SmallVideosService {

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;// 获取存储服务器的请求URL

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private FocusUserApi focusUserApi;

    @DubboReference
    private CommentApi commentApi;

    @Autowired
    private MqMessageService mqMessageService;

    //发布视频
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        String originalFilename = videoFile.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //上传视频到Fdfs                                     输入流            文件大小             文件后缀名   作者信息
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
        //                          访问路径              文件在fdfs中的文件夹路径和文件名
        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();
        //上传视频封面到阿里云OSS
        String upload = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        Video video = new Video();
        video.setUserId(UserHolder.getId());
        video.setText("爱意随风起,风止意难平");
        video.setPicUrl(upload);
        video.setVideoUrl(videoUrl);
        //将数据保存到数据库
        String id = videoApi.save(video);
        mqMessageService.sendLogService(UserHolder.getId(), "0301", "video", id);

    }

    ////分页查看视屏
    public PageResult getVideos(Integer page, Integer pagesize) {
        //获得redis的推荐数据
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getId();
        String redisValue = redisTemplate.opsForValue().get(key);
        //List<Integer> collect = Collections.emptyList();
        List<Video> list = Collections.emptyList();
        Integer foller = 0;
        //判断redis中取出的数据是否为空,为空就代表reids中没有推荐数据
        if (StringUtils.isNotEmpty(redisValue)) {
            String[] split = redisValue.split(",");
            //获取redis中获取的数据最多可以分多少页
            int redisPage = PageUtil.totalPage(split.length, page);
            foller = split.length % pagesize == 0 ? 0 : pagesize - split.length % pagesize;
            //读取的数据的起始索引
            Integer startIndex = (page - 1) * pagesize;
            if (page <= redisPage) {
                List<Integer> collect = Arrays.stream(split).map(s -> Integer.parseInt(s))
                        .skip(startIndex).limit(pagesize).collect(Collectors.toList());
                list = videoApi.getVideo(collect);
                //如果数据长度小于pagesize, 就去MongoDB数据库中读取剩余几条
                if (list.size() < pagesize) {
                    List<Video> videos = videoApi.getSupplement(foller);
                    list.addAll(videos);
                }
            }

        }
        //判断list集合中有没有数据,有数据就代表查到了,没有数据就冲MongoDB中查
        if (CollUtil.isEmpty(list)) {
            list = videoApi.getPageVideo(page, pagesize, foller);
        }
        //判断数据库中有没有读出数据
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //从list中获得发布人id
        List<Long> userId = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.getByUserIds(userId, null);
        //List<VideoVo> vos = Collections.emptyList();
        List<VideoVo> vos = new ArrayList<>();
        for (Video video : list) {
            UserInfo userInfo = map.get(video.getUserId());
            if (userInfo != null) {
                VideoVo vo = VideoVo.init(userInfo, video);
                if (redisTemplate.opsForHash().hasKey(Constants.VIDEO_LIKE_HASHKEY + video.getId(),
                        UserHolder.getId().toString())) {
                    vo.setHasLiked(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page, pagesize, 0L, vos);

    }

    //关注和取消关注
    public void Focus(Long id, boolean b) {
        //获取操作用户id
        Long userId = UserHolder.getId();
        FocusUser focusUser = new FocusUser();
        focusUser.setUserId(userId);
        focusUser.setFollowUserId(id);
        try {
            //判断操作
            if (b) {
                //进行新增操作
                focusUser.setCreated(System.currentTimeMillis());
                focusUserApi.save(focusUser);
            } else {
                //进行删除操作
                focusUserApi.delete(focusUser);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorResult.error());
        }
    }

    //点赞和取消点赞
    public void VideoLike(ObjectId videoId, boolean b) {
        //获取当前用户
        Long userId = UserHolder.getId();
        //封装数据
        Comment comment = new Comment();
        comment.setPublishId(videoId);
        comment.setUserId(userId);
        //判断当前操作
        if (b) {
            //从数据库中读取发布视频的用户id
            /*Video video = videoApi.getById(videoId);
            if (ObjectUtil.isNotEmpty(video)) {
                comment.setPublishUserId(video.getUserId());
            }*/
            //保存到数据库
            commentApi.saveVideo(comment, CommentType.LIKE);
            //保存到redis中
            redisTemplate.opsForHash().put(Constants.VIDEO_LIKE_HASHKEY + videoId, userId.toString(), "1");
            mqMessageService.sendLogService(UserHolder.getId(), "0302", "video", videoId.toHexString());
        } else {
            //从数据中删除对应的点赞数据
            commentApi.deleteVideo(comment, CommentType.LIKE);
            //删除redis中的点赞记录
            redisTemplate.opsForHash().delete(Constants.VIDEO_LIKE_HASHKEY + videoId, userId.toString());
            mqMessageService.sendLogService(UserHolder.getId(), "0303", "video", videoId.toHexString());
        }

    }

    //查看视频评论
    public PageResult getComments(Integer page, Integer pagesize, ObjectId id) {
        //获得分页的评论数据
        List<Comment> comments = commentApi.getComments(page, pagesize, id);
        //判断是否有数据
        if (CollUtil.isEmpty(comments)) {
            return new PageResult();
        }
        //取出评论人id
        List<Long> userId = CollUtil.getFieldValues(comments, "userId", Long.class);
        //查询对应的用户详情
        Map<Long, UserInfo> map = userInfoApi.getByUserIds(userId, null);

        List<CommentVo> list = new ArrayList<>();
        //封装数据
        for (Comment comment : comments) {
            UserInfo userInfo = map.get(comment.getUserId());
            if (userId != null) {
                CommentVo vo = CommentVo.init(userInfo, comment);
                //判断当前用户是否对该评论进行了点赞
                if (redisTemplate.opsForHash().hasKey(Constants.COMMENT_INTERACT + comment.getId(),
                        Constants.COMMENT_LIKE_HASHKEY + UserHolder.getId())) {
                    vo.setHasLiked(1);
                }
                list.add(vo);
            }
        }
        return new PageResult(page, pagesize, 0L, list);
    }

    //发布评论
    public void saveComment(ObjectId id, String text) {
        //获得当前用户id
        Long userId = UserHolder.getId();
        //封装对象
        Comment comment = new Comment();
        comment.setUserId(userId);
        comment.setPublishId(id);
        comment.setContent(text);
        //保存数据库
        Comment comment1 = commentApi.saveVideo(comment, CommentType.COMMENT);
        mqMessageService.sendLogService(UserHolder.getId(), "0304", "video",
                comment1.getId().toHexString());

    }

    //视频评论点赞和取消点赞
    public void VideoCommentLike(ObjectId id, boolean b) {
        //获取当前用户id
        Long userId = UserHolder.getId();
        //封装对象
        Comment comment = new Comment();
        comment.setUserId(userId);
        comment.setPublishId(id);
        comment.setCommentType(2);
        //判断操作
        if (b) {
            comment.setCreated(System.currentTimeMillis());
            //进行添加操作
            Comment comment1 = commentApi.saveComment(comment);
            //保存到redis
            redisTemplate.opsForHash().put(Constants.COMMENT_INTERACT + id,
                    Constants.COMMENT_LIKE_HASHKEY + userId, "1");
        } else {
            //进行删除操作
            Comment comment1 = commentApi.deleteComment(comment);
            //删除在redis中对应的数据
            redisTemplate.opsForHash().delete(Constants.COMMENT_INTERACT + id,
                    Constants.COMMENT_LIKE_HASHKEY + userId);
        }
    }
}
